import { ATTR_NODE } from './node';

// 暴露出去的全局属性
export const commonInfo = {
  onlyRead: true
};

// 初始化G6
export function initG6(opts) {
  const { graphData, jsonData } = opts;
  const { graph, onlyRead, canvasWidth, canvasHeight } = graphData;
  commonInfo.onlyRead = onlyRead;
  graph?.clear?.();
  graph?.destroy?.();
  const dom = document.getElementById(graphData.canvasId);
  if (!dom) return;
  const defaultData = JSON.parse(jsonData || '{}');
  const SnapLine = new G6.SnapLine({
    line: {
      lineWidth: 3
    },
    itemAlignType: true
  }); // 辅助线插件
  const grid = new G6.Grid(); // 网格线
  const toolbar = new G6.ToolBar({
    container: graphData.toolbarId,
    handleClick(code, toolbarGraph) {
      const point = toolbarGraph.getGraphCenterPoint();
      if (code === 'zoomOut') {
        toolbarGraph.zoom(1.1, point);
      }
      if (code === 'zoomIn') {
        toolbarGraph.zoom(0.9, point);
      }
      if (code === 'realZoom') {
        toolbarGraph.zoomTo(1);
        toolbarGraph.moveTo(0, 0);
      }
      if (code === 'autoZoom') {
        toolbarGraph.fitView();
      }
      if (code === 'undo') {
        toolbar.undo();
      }
      if (code === 'redo') {
        toolbar.redo();
      }
    }
  }); // 工具插件
  const newGraph = new G6.Graph({
    renderer: 'canvas',
    container: graphData.canvasId, // String | HTMLElement，必须
    fitView: true, // 默认看全图
    fitViewPadding: 0, // 图自适应画布时的四周留白像素值
    enabledStack: true, // 启用栈功能
    width: canvasWidth, // Number，必须，图的宽度
    height: canvasHeight, // Number，必须，图的高度
    modes: {
      default: onlyRead
        ? [
            'drag-canvas',
            'scroll-canvas',
            {
              type: 'click-select',
              multiple: false
            }
          ]
        : [
            'click-select',
            'drag-node',
            'brush-select',
            'drag-canvas',
            'scroll-canvas'
          ]
    },
    plugins: onlyRead ? [toolbar] : [SnapLine, grid, toolbar] // 插件
  });
  newGraph.data(defaultData);
  newGraph.render(); // 渲染图
  graphData.graph = newGraph;
  resetIndex(graphData);
  // 节点事件
  addEvent(graphData);
  setActive({ graphData, node: null });
}

// 将会议室/桌子的层级降到最低
function resetIndex(graphData) {
  const { graph } = graphData;
  const nodes = graph.getNodes();
  nodes.forEach(node => {
    if (node.getModel().node_type === 'desk') node.toBack();
  });
  nodes.forEach(node => {
    if (node.getModel().node_type === 'room') node.toBack();
  });
}

// 添加节点事件
function addEvent(graphData) {
  const { graph, onlyRead } = graphData;
  // 空白点击事件
  graph.on('canvas:click', () => {
    setActive({ graphData, node: null });
  });
  // 节点点击事件
  graph.on('node:click', ev => {
    const node = ev.item; // 节点
    const model = node?.getModel?.();
    if (onlyRead && model?.custom_info?.is_link) {
      setActive({ graphData, node: null });
      node?.setState?.('selected', false);
      graphData.router.push({
        name: 'CustomSeatsDetail',
        query: {
          parent_node_id: node._cfg.id,
          node_label: node.getModel?.().custom_info?.node_label
        }
      });
      return;
    }
    const states = node._cfg.states;
    if (states.includes('selected')) {
      setActive({ graphData, node });
    } else {
      setActive({ graphData, node: null });
    }
  });

  // 员工节点超出显示...
  const hoverNameList = ['user-node', 'user-top-group', 'user-bottom-group'];
  hoverNameList.forEach(nodeName => {
    graph.on(`${nodeName}:mouseenter`, e => {
      graph.setItemState(e.item, 'user-node-hover', true);
    });
    graph.on(`${nodeName}:mouseleave`, e => {
      graph.setItemState(e.item, 'user-node-hover', false);
    });
  });

  // 拖动修改尺寸事件
  const sizeInfo = {
    x: 0,
    y: 0,
    distanceX: 0,
    distanceY: 0,
    hasMove: false,
    canChangeSize: false,
    node: {},
    shapeName: ''
  };

  // 节点：鼠标按下
  graph.on('node:mousedown', e => {
    const targetName = e.target.cfg.name;
    const nameList = ['top-point', 'right-point', 'bottom-point', 'left-point'];
    if (!nameList.includes(targetName)) {
      sizeInfo.canChangeSize = false;
      return;
    }
    sizeInfo.shapeName = targetName;
    sizeInfo.canChangeSize = true;
    sizeInfo.x = e.x;
    sizeInfo.y = e.y;
    sizeInfo.distanceX = e.item?.getModel?.().x - e.x;
    sizeInfo.distanceY = e.item?.getModel?.().y - e.y;
    sizeInfo.hasMove = false;
    sizeInfo.node = e.item;
    window.removeEventListener('mouseup', windowkeyupEvent);
    window.addEventListener('mouseup', windowkeyupEvent);
  });

  // 节点：鼠标移动
  graph.on('mousemove', e => {
    if (!sizeInfo.canChangeSize) return;
    const model = sizeInfo.node.getModel();
    if (model.node_type === 'circle') changeCircleSize(e, sizeInfo, graphData);
    else changenode_size(e, sizeInfo, graphData);
  });

  // window：鼠标松开
  function windowkeyupEvent() {
    sizeInfo.canChangeSize = false;
    window.removeEventListener('mouseup', windowkeyupEvent);
  }
}

// 修改节点尺寸
function changenode_size(e, sizeInfo, graphData) {
  const { graph } = graphData;
  const node = sizeInfo.node;
  const model = node.getModel();
  const _custom_info = model.custom_info;
  const { node_width, node_height } = _custom_info;
  let speedX, speedY, positionX, positionY;
  const shapeName = sizeInfo.shapeName;
  if (shapeName === 'top-point') {
    speedY = sizeInfo.y - e.y;
    positionY = model.y - speedY;
  }
  if (shapeName === 'right-point') {
    speedX = e.x - sizeInfo.x;
  }
  if (shapeName === 'bottom-point') {
    speedY = e.y - sizeInfo.y;
  }
  if (shapeName === 'left-point') {
    speedX = sizeInfo.x - e.x;
    positionX = model.x - speedX;
  }
  let newWidth = node_width + (speedX || 0);
  let newHeight = node_height + (speedY || 0);

  sizeInfo.x = e.x;
  sizeInfo.y = e.y;
  if (newWidth <= 1) {
    newWidth = 1;
    sizeInfo.x = model.x;
    if (positionX) positionX = model.x + _custom_info.node_width - newWidth;
  }
  if (newHeight <= 1) {
    newHeight = 1;
    sizeInfo.y = model.y;
    if (positionY) positionY = model.y + _custom_info.node_height - newHeight;
  }
  _custom_info.node_width = newWidth;
  _custom_info.node_height = newHeight;
  model.x = positionX ?? model.x;
  model.y = positionY ?? model.y;
  if (
    (newWidth != node_width || newHeight != node_height) &&
    !sizeInfo.hasMove
  ) {
    graph.updateItem(node, node.getModel());
    sizeInfo.hasMove = true;
  }
  graph.updateItem(node, model, false);
  setActive({ graphData, node: node });
}

// 修改圆形尺寸
function changeCircleSize(e, sizeInfo, graphData) {
  const { graph } = graphData;
  const node = sizeInfo.node;
  const model = node.getModel();
  const _custom_info = model.custom_info;
  const { node_size } = _custom_info;
  let speed;
  const shapeName = sizeInfo.shapeName;
  if (shapeName === 'top-point') {
    speed = sizeInfo.y - e.y;
  }
  if (shapeName === 'right-point') {
    speed = e.x - sizeInfo.x;
  }
  if (shapeName === 'bottom-point') {
    speed = e.y - sizeInfo.y;
  }
  if (shapeName === 'left-point') {
    speed = sizeInfo.x - e.x;
  }
  let newSize = node_size + (speed || 0);

  sizeInfo.x = e.x;
  sizeInfo.y = e.y;
  if (newSize <= 1) {
    newSize = 1;
    sizeInfo.x = model.x;
    sizeInfo.y = model.y;
  }
  _custom_info.node_size = newSize;
  if (newSize != node_size && !sizeInfo.hasMove) {
    graph.updateItem(node, node.getModel());
    sizeInfo.hasMove = true;
  }
  graph.updateItem(node, model, false);
  setActive({ graphData, node: node });
}

// 定义当前正在操作的节点
export async function setActive(opts) {
  const { graphData, node } = opts;
  const { changeInfoActive, activeNode } = graphData;
  if (!node) {
    activeNode?.setState?.('selected', false);
    graphData.activeNode = null;
    changeInfoActive('1');
    return;
  }
  graphData.activeNode = node;
  const model = node?.getModel(); // 属性
  graphData.editForm = JSON.parse(JSON.stringify(model?.custom_info || {}));
  node?.setState?.('selected', true);
  changeInfoActive('2');
}

// 保存节点
export function saveNode(opts, graphData) {
  const { addModel, node, isDelete } = opts;
  const { graph, activeNode } = graphData;
  if (isDelete) {
    const nodeId = node.id;
    graph.removeItem(nodeId);
    if (addModel) addNode(addModel, graphData, nodeId);
    return;
  }
  const nodeId = activeNode._cfg.id;
  graph.removeItem(nodeId);
  const newNode = addNode(addModel, graphData, nodeId);
  setActive({ graphData, node: newNode });
}

// 添加节点
export function addNode(addModel, graphData, nodeId) {
  const { graph } = graphData;
  const newNode = graph.addItem('node', {
    ...addModel,
    id: nodeId || `node-${Date.now()}-${Math.random()}` // String，该节点存在则必须，节点的唯一标识
  });
  resetIndex(graphData);
  return newNode;
}

// 切换模式
export function changeModel(graphData) {
  graphData.onlyRead = !graphData.onlyRead;
  initSize(graphData);
}

// 保存json
export function saveCanvas(graphData) {
  const jsonData = graphData.graph?.save?.() || {};
  return JSON.stringify(jsonData);
}

// 按键按下
const keyDownObj = {};
export function watchkeyDown(ev, graphData) {
  const keyCode = ev.keyCode;
  const ctrlKey = ev.ctrlKey;
  const shiftKey = ev.shiftKey;

  keyDownObj[keyCode] = true;
  const { graph, onlyRead } = graphData;
  const codeList = [46, 38, 40, 37, 39, 8, 86];
  if (!codeList.includes(keyCode) || onlyRead) return;

  const selectedNodes = graph.findAllByState('node', 'selected');
  if (!selectedNodes?.length) return;

  // 删除键
  if (keyCode === 46 || (ctrlKey && keyCode === 8)) {
    setActive({ graphData, node: null });
    selectedNodes.forEach(node => graph.removeItem(node));
    return;
  }
  // 上
  if (ctrlKey && keyCode === 38) {
    selectedNodes.forEach(node => {
      const model = node?.getModel();
      model.y -= 1;
      graph.updateItem(node, model);
    });
  }
  // 下
  if (ctrlKey && keyCode === 40) {
    selectedNodes.forEach(node => {
      const model = node?.getModel();
      model.y += 1;
      graph.updateItem(node, model);
    });
  }
  // 左
  if (ctrlKey && keyCode === 37) {
    selectedNodes.forEach(node => {
      const model = node?.getModel();
      model.x -= 1;
      graph.updateItem(node, model);
    });
  }
  // 右
  if (ctrlKey && keyCode === 39) {
    selectedNodes.forEach(node => {
      const model = node?.getModel();
      model.x += 1;
      graph.updateItem(node, model);
    });
  }
  // 复制
  if (ctrlKey && shiftKey && keyCode === 86) {
    const flag = Math.random() > 0.5 ? true : false;
    const speedX = flag ? Math.random() * 200 : -Math.random() * 200;
    const speedY = flag ? Math.random() * 200 : -Math.random() * 200;
    selectedNodes.forEach(node => {
      const _model = JSON.parse(JSON.stringify(node.getModel()));
      delete _model.id;
      _model.x += speedX;
      _model.y += speedY;
      if (_model.node_name === 'user-some-node') {
        _model.type = 'user-none-node';
        _model.node_name = 'user-none-node';
      }
      initEditForm(_model.custom_info || {});
      const newNode = addNode(_model, graphData);
      node?.setState?.('selected', false);
      newNode?.setState?.('selected', true);
    });
  }
}
// 按键松开
export function keyUpEvent(ev) {
  const keyCode = ev.keyCode;
  delete keyDownObj[keyCode];
}

// 处理宽高
export async function initSize(graphData, notRoload) {
  await nextTick();
  const { graph, canvasContentRef } = graphData;
  graphData.canvasWidth = canvasContentRef.clientWidth - 2;
  graphData.canvasHeight = window.innerHeight - 128 - 2;
  if (notRoload) {
    graph?.changeSize?.(graphData.canvasWidth, graphData.canvasHeight);
  } else {
    initG6({ graphData, jsonData: saveCanvas(graphData) });
  }
}

// 从菜单拖拽结束
export function dragend(e, item, graphData) {
  const { graph, canvasWidth, canvasHeight } = graphData;
  const point = graph.getPointByClient(e.clientX, e.clientY);
  const canvasPoint = graph.getCanvasByPoint(point.x, point.y);
  const x = canvasPoint.x;
  const y = canvasPoint.y;
  if (x <= 0 || y <= 0 || x >= canvasWidth || y >= canvasHeight) {
    return;
  }
  const ITEM_ATTR = ATTR_NODE[item.nodeKey];
  let addX = point.x - ITEM_ATTR.custom_info.node_width / 2;
  let addY = point.y - ITEM_ATTR.custom_info.node_height / 2;
  // 圆的坐标在圆心
  if (ITEM_ATTR.node_type === 'circle') {
    addX = point.x;
    addY = point.y;
  }
  // 经过旋转后的组件要手动调整下
  if (ITEM_ATTR.node_name === 'left-door-node') {
    addX += ITEM_ATTR.custom_info.node_height / 2 - 30;
    addY += 30;
  }
  if (ITEM_ATTR.node_name === 'right-door-node') {
    addX -= ITEM_ATTR.custom_info.node_height / 2 - 30;
    addY += 35;
  }
  const addInfo = {
    x: addX,
    y: addY,
    ...ITEM_ATTR
  };
  if (graphData.canvasRoom === 'index') {
    addInfo.custom_info.is_link = false;
  }
  addNode(addInfo, graphData);
}

// 初始化用户信息
export function initEditForm(_form) {
  _form.user_id = 0;
  _form.user_name = '';
  _form.user_dept = '';
  _form.user_show_dept = '';
  _form.user_position = '';
  _form.user_role = '';
  _form.user_phone = '';
}

// 重新刷新最新用户信息
export function refreshUserNode(nodes, userList) {
  const userMap = {};
  deepUserList(userList, userMap);
  nodes.forEach(node => {
    const _custom_info = node.custom_info || {};
    if (node.node_name !== 'user-some-node' || !_custom_info.user_id) return;
    const newUserInfo = userMap[_custom_info.user_id];
    if (!newUserInfo || newUserInfo.label?.includes('已删除')) {
      node.node_name = 'user-none-node';
      node.type = 'user-none-node';
      return initEditForm(_custom_info);
    }
    _custom_info.user_name = newUserInfo.label;
    _custom_info.user_dept = newUserInfo.dept;
  });
}

// 递归用户
export function deepUserList(list, userMap, parent) {
  for (let i = 0; i < list.length; i++) {
    const item = list[i];
    item.deptList = JSON.parse(JSON.stringify(parent?.deptList || []));
    if (item.children?.length) {
      item.deptList.push(item.label);
      deepUserList(item.children, userMap, item);
    } else {
      let oldDept = userMap[item.value]?.dept || '';
      if (oldDept) oldDept = oldDept + '\n\n';
      const nowDept = item.deptList?.join('-');
      item.dept = oldDept + nowDept;
      userMap[item.value] = item;
    }
  }
}
